package litegame

import (
	"bytes"
	"corelib/log"
	"fmt"
	"io/ioutil"
	"net/http"

	jsoniter "github.com/json-iterator/go"
)

var json = jsoniter.ConfigCompatibleWithStandardLibrary

// 微信小游戏/小程序 登录凭证校验
// 文档地址: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html

// 登录凭证
type WechatSession struct {
	OpenID     string `json:"openid"`      // 用户唯一标识
	SessionKey string `json:"session_key"` // 会话密钥
	Unionid    string `json:"unionid"`     // 用户在开放平台的唯一标识符，若当前小程序已绑定到微信开放平台账号下会返回，详见 UnionID 机制说明。
	BaseErrRet
}

const _JSCODE_2_SESSION_URL = `https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code`

// 验证
func code2Session(appID string, appSecret string, code string) (*WechatSession, error) {
	var session *WechatSession

	// 拼接访问地址
	tUrl := fmt.Sprintf(_JSCODE_2_SESSION_URL, appID, appSecret, code)

	// http请求
	err, tHttpStatus, tData := httpGet(tUrl)

	if nil != err {
		return session, err
	}

	// 返回信息解码
	if nil != tData {
		session = &WechatSession{}

		errJson := json.Unmarshal(tData, session)

		return session, errJson
	} else {
		return session, fmt.Errorf("respone is nil. http status(%d)", tHttpStatus)
	}

	return session, nil
}

// http get 调用
func httpGet(tUrl string) (error, int, []byte) {
	//默认返回状态为  StatusBadRequest = 400 // RFC 7231, 6.5.1
	tHttpStatus := http.StatusBadRequest //StatusNotFound

	//访问指定网页
	resp, err := http.Get(tUrl)
	//判断是否发生错误
	if err != nil {
		//如果有返回 则return 返回结果中的状态值
		if nil != resp {
			tHttpStatus = resp.StatusCode
		}
		//返回错误
		return err, tHttpStatus, nil
	}

	//退出处理
	defer func() {
		if (nil != resp) && (nil != resp.Body) {
			//释放 返回的消息体
			resp.Body.Close()
		}
	}()

	//判断 请求是否成功
	if nil != resp {
		if nil == resp.Body {
			//请求结果为空 返回错误
			return nil, tHttpStatus, nil
		}
		tHttpStatus = resp.StatusCode
		//2开头 （请求成功）表示成功处理了请求的状态代码
		if (tHttpStatus < 200) || (tHttpStatus > 299) {
			//返回错误
			return nil, tHttpStatus, nil
		}
	} else {
		//请求结果为空 返回错误
		return nil, tHttpStatus, nil
	}

	//读取 返回结果集的内容
	body, err := ioutil.ReadAll(resp.Body)
	//判断是否发生错误
	if err != nil {
		//如果有返回 则return 返回结果中的状态值
		if nil != resp {
			tHttpStatus = resp.StatusCode
		}

		//返回错误
		return err, tHttpStatus, nil
	}

	log.Println("httpGet !!! body=", string(body))

	//返回 结果
	return nil, resp.StatusCode, body
}

func httpPost(tUrl string, data []byte) (error, int, []byte) {
	//默认返回状态为  StatusBadRequest = 400 // RFC 7231, 6.5.1
	tHttpStatus := http.StatusBadRequest //StatusNotFound

	resp, err := http.Post(tUrl, "application/json", bytes.NewReader(data))
	//判断是否发生错误
	if err != nil {
		//如果有返回 则return 返回结果中的状态值
		if nil != resp {
			tHttpStatus = resp.StatusCode
		}
		//返回错误
		return err, tHttpStatus, nil
	}

	//退出处理
	defer func() {
		if (nil != resp) && (nil != resp.Body) {
			//释放 返回的消息体
			resp.Body.Close()
		}
	}()

	//判断 请求是否成功
	if nil != resp {
		if nil == resp.Body {
			//请求结果为空 返回错误
			return nil, tHttpStatus, nil
		}
		tHttpStatus = resp.StatusCode
		//2开头 （请求成功）表示成功处理了请求的状态代码
		if (tHttpStatus < 200) || (tHttpStatus > 299) {
			//返回错误
			return nil, tHttpStatus, nil
		}
	} else {
		//请求结果为空 返回错误
		return nil, tHttpStatus, nil
	}

	//读取 返回结果集的内容
	body, err := ioutil.ReadAll(resp.Body)
	//判断是否发生错误
	if err != nil {
		//如果有返回 则return 返回结果中的状态值
		if nil != resp {
			tHttpStatus = resp.StatusCode
		}

		//返回错误
		return err, tHttpStatus, nil
	}

	log.Println("httpPost !!! body=", string(body))

	//返回 结果
	return nil, resp.StatusCode, body
}
